package util

import (
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"net"
	"path/filepath"
	"reflect"
	"regexp"
	"sync"
	"time"

	"github.com/Chain-Zhang/pinyin"
)

func ContainsInt64(array []int64, val int64) (index int) {
	index = -1
	for i := 0; i < len(array); i++ {
		if array[i] == val {
			index = i
			return
		}
	}
	return
}

// ContainsInt Returns the index position of the int val in array
func ContainsInt(array []int, val int) (index int) {
	index = -1
	for i := 0; i < len(array); i++ {
		if array[i] == val {
			index = i
			return
		}
	}
	return
}

// ContainsString Returns the index position of the string val in array
func ContainsString(array []string, val string) (index int) {
	index = -1
	for i := 0; i < len(array); i++ {
		if array[i] == val {
			index = i
			return
		}
	}
	return
}

func GetIpFromAddr(addr net.Addr) net.IP {
	var ip net.IP
	switch v := addr.(type) {
	case *net.IPNet:
		ip = v.IP
	case *net.IPAddr:
		ip = v.IP
	}
	if ip == nil || ip.IsLoopback() {
		return nil
	}
	ip = ip.To4()
	if ip == nil {
		return nil // not an ipv4 address
	}

	return ip
}

func GetLocalIPList() (ipList []net.IP) {
	faces, err := net.Interfaces()
	if err != nil {
		return
	}
	for _, face := range faces {
		if face.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if face.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrList, err := face.Addrs()
		if err != nil {
			continue
		}
		for _, addr := range addrList {
			ip := GetIpFromAddr(addr)
			if ip == nil {
				continue
			}
			ipList = append(ipList, ip)
		}
	}
	return
}

func FormatPath(path string) string {

	var abs string
	abs, err := filepath.Abs(path)
	if err != nil {
		return path
	}
	res := filepath.ToSlash(abs)
	return res
}

func ToJSON(data interface{}) string {
	if data != nil {
		bs, _ := json.Marshal(data)
		if bs != nil {
			return string(bs)
		}
	}
	return ""
}

func ToBean(bytes []byte, req interface{}) (err error) {
	err = json.Unmarshal(bytes, req)
	return
}

//GetNowTime 获取当前时间戳
func GetNowTime() int64 {
	return GetTimeTime(time.Now())
}

//GetTimeTime 获取当前时间戳
func GetTimeTime(time time.Time) int64 {
	return time.UnixNano() / 1e6
}

//Now 获取当前时间
func Now() time.Time {
	return time.Now()
}

func NowStr() string {
	now := time.Now()
	return Format(now)
}

func Format(date time.Time) string {
	return date.Format("2006-01-02 15:04:05.000")
}

func MatchEmail(email string) bool {
	pattern := `^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$` //匹配电子邮箱
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(email)
}

func MatchPhone(phone string) bool {
	pattern := `^\d+$` //匹配手机
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(phone)
}

func MatchNumber(num string) bool {
	pattern := `^\d+$` //匹配数字
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(num)
}

func MatchAccount(account string) bool {
	pattern := `^[a-zA-Z0-9_]+$` //匹配账号
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(account)
}

var (
	//设置随机数种子
	randForRandomInt = rand.New(rand.NewSource(time.Now().UnixNano()))
)

// RandomInt 获取随机数
func RandomInt(min int, max int) (res int, err error) {
	if max < min {
		err = errors.New(fmt.Sprint("RandomInt error,min:", min, ",max:", max))
		return
	}
	res = min + randForRandomInt.Intn(max-min+1)
	return
}

// RandomString 获取随机字符串
func RandomString(minLen int, maxLen int) (res string, err error) {
	len := minLen
	if maxLen > minLen {
		len, err = RandomInt(minLen, maxLen)
		if err != nil {
			return
		}
	}
	for i := 0; i < len; i++ {
		randNum := 0
		randNum, err = RandomInt(0, randChatsSize*3)
		if err != nil {
			return
		}
		res += randChats[randNum%randChatsSize]
	}
	return
}

// RandomUserName 随机姓名
func RandomUserName(minLen int, maxLen int) (res string, err error) {
	len := minLen - 1
	if maxLen > minLen {
		len, err = RandomInt(minLen, maxLen)
		if err != nil {
			return
		}
	}
	randomNum := 0
	randomNum, err = RandomInt(0, firstNameLen*3)
	if err != nil {
		return
	}
	res = firstName[randomNum%firstNameLen]
	for i := 0; i < len; i++ { //随机产生2位或者3位的名

		randomNum, err = RandomInt(0, lastNameLen*3+i)
		if err != nil {
			return
		}
		res += lastName[randomNum%lastNameLen]
	}
	return
}

func ToPinYin(str string) (string, error) {
	// InitialsInCapitals: 首字母大写, 不带音调
	// WithoutTone: 全小写,不带音调
	// Tone: 全小写带音调
	str, err := pinyin.New(str).Split("").Mode(pinyin.WithoutTone).Convert()
	if err != nil {
		// 错误处理
		return "", err
	}
	return str, nil
}

func IsZero(value interface{}) (isZero bool) {
	zero := reflect.Zero(reflect.TypeOf(value)).Interface()
	isZero = reflect.DeepEqual(value, zero)
	return
}

var (
	lockMapLock = sync.Mutex{}
	lockMap     = make(map[string]*sync.Mutex)
)

func GetLock(key string) (lock *sync.Mutex) {

	lockMapLock.Lock()

	defer lockMapLock.Unlock()

	var ok bool
	lock, ok = lockMap[key]
	if ok {
		return
	}
	lock = &sync.Mutex{}
	lockMap[key] = lock
	return lock
}

type ColumnType struct {
	Column    string
	FieldType *reflect.StructField
	Value     *reflect.Value
}

func GetRefValue(bean interface{}) reflect.Value {
	if IsPtr(bean) {
		return reflect.ValueOf(bean).Elem()
	}
	return reflect.ValueOf(bean)
}

func GetRefType(bean interface{}) reflect.Type {
	if IsPtr(bean) {
		return reflect.TypeOf(bean).Elem()
	}
	return reflect.TypeOf(bean)
}

func IsPtr(v interface{}) bool {
	return reflect.ValueOf(v).Kind() == reflect.Ptr
}

var (
	randChats = []string{
		"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
		"a", "b", "c", "d", "e", "f", "g",
		"h", "i", "j", "k", "l", "m", "n",
		"o", "p", "q", "r", "s", "t", "u",
		"v", "w", "z", "y", "z",
		"A", "B", "C", "D", "E", "F", "G",
		"H", "I", "J", "K", "L", "M", "N",
		"O", "P", "Q", "R", "S", "T", "U",
		"V", "W", "Z", "Y", "Z",
		"_",
	}
	randChatsSize = len(randChats)

	firstName = []string{
		"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋",
		"沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏",
		"陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭",
		"郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "任", "袁", "柳", "鲍", "史", "唐", "费", "薛",
		"雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "安", "常", "傅", "卞", "齐", "元", "顾", "孟",
		"平", "黄", "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "狄", "米", "伏", "成", "戴", "谈",
		"宋", "茅", "庞", "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "季", "贾",
		"路", "娄", "江", "童", "颜", "郭", "梅", "盛", "林", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田",
		"樊", "胡", "凌", "霍", "虞", "万", "支", "柯", "管", "卢", "莫", "柯", "房", "裘", "缪", "解", "应",
		"宗", "丁", "宣", "邓", "单", "杭", "洪", "包", "诸", "左", "石", "崔", "吉", "龚", "程", "嵇", "邢",
		"裴", "陆", "荣", "翁", "荀", "于", "惠", "甄", "曲", "封", "储", "仲", "伊", "宁", "仇", "甘", "武",
		"符", "刘", "景", "詹", "龙", "叶", "幸", "司", "黎", "溥", "印", "怀", "蒲", "邰", "从", "索", "赖",
		"卓", "屠", "池", "乔", "胥", "闻", "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵",
		"冉", "宰", "雍", "桑", "寿", "通", "燕", "浦", "尚", "农", "温", "别", "庄", "晏", "柴", "瞿", "阎",
		"连", "习", "容", "向", "古", "易", "廖", "庾", "终", "步", "都", "耿", "满", "弘", "匡", "国", "文",
		"寇", "广", "禄", "阙", "东", "欧", "利", "师", "巩", "聂", "关", "荆", "司马", "上官", "欧阳", "夏侯",
		"诸葛", "闻人", "东方", "赫连", "皇甫", "尉迟", "公羊", "澹台", "公冶", "宗政", "濮阳", "淳于", "单于",
		"太叔", "申屠", "公孙", "仲孙", "轩辕", "令狐", "徐离", "宇文", "长孙", "慕容", "司徒", "司空"}
	lastName = []string{
		"伟", "刚", "勇", "毅", "俊", "峰", "强", "军", "平", "保", "东", "文", "辉", "力", "明", "永", "健", "世", "广", "志", "义",
		"兴", "良", "海", "山", "仁", "波", "宁", "贵", "福", "生", "龙", "元", "全", "国", "胜", "学", "祥", "才", "发", "武", "新",
		"利", "清", "飞", "彬", "富", "顺", "信", "子", "杰", "涛", "昌", "成", "康", "星", "光", "天", "达", "安", "岩", "中", "茂",
		"进", "林", "有", "坚", "和", "彪", "博", "诚", "先", "敬", "震", "振", "壮", "会", "思", "群", "豪", "心", "邦", "承", "乐",
		"绍", "功", "松", "善", "厚", "庆", "磊", "民", "友", "裕", "河", "哲", "江", "超", "浩", "亮", "政", "谦", "亨", "奇", "固",
		"之", "轮", "翰", "朗", "伯", "宏", "言", "若", "鸣", "朋", "斌", "梁", "栋", "维", "启", "克", "伦", "翔", "旭", "鹏", "泽",
		"晨", "辰", "士", "以", "建", "家", "致", "树", "炎", "德", "行", "时", "泰", "盛", "雄", "琛", "钧", "冠", "策", "腾", "楠",
		"榕", "风", "航", "弘", "秀", "娟", "英", "华", "慧", "巧", "美", "娜", "静", "淑", "惠", "珠", "翠", "雅", "芝", "玉", "萍",
		"红", "娥", "玲", "芬", "芳", "燕", "彩", "春", "菊", "兰", "凤", "洁", "梅", "琳", "素", "云", "莲", "真", "环", "雪", "荣",
		"爱", "妹", "霞", "香", "月", "莺", "媛", "艳", "瑞", "凡", "佳", "嘉", "琼", "勤", "珍", "贞", "莉", "桂", "娣", "叶", "璧",
		"璐", "娅", "琦", "晶", "妍", "茜", "秋", "珊", "莎", "锦", "黛", "青", "倩", "婷", "姣", "婉", "娴", "瑾", "颖", "露", "瑶",
		"怡", "婵", "雁", "蓓", "纨", "仪", "荷", "丹", "蓉", "眉", "君", "琴", "蕊", "薇", "菁", "梦", "岚", "苑", "婕", "馨", "瑗",
		"琰", "韵", "融", "园", "艺", "咏", "卿", "聪", "澜", "纯", "毓", "悦", "昭", "冰", "爽", "琬", "茗", "羽", "希", "欣", "飘",
		"育", "滢", "馥", "筠", "柔", "竹", "霭", "凝", "晓", "欢", "霄", "枫", "芸", "菲", "寒", "伊", "亚", "宜", "可", "姬", "舒",
		"影", "荔", "枝", "丽", "阳", "妮", "宝", "贝", "初", "程", "梵", "罡", "恒", "鸿", "桦", "骅", "剑", "娇", "纪", "宽", "苛",
		"灵", "玛", "媚", "琪", "晴", "容", "睿", "烁", "堂", "唯", "威", "韦", "雯", "苇", "萱", "阅", "彦", "宇", "雨", "洋", "忠",
		"宗", "曼", "紫", "逸", "贤", "蝶", "菡", "绿", "蓝", "儿", "翠", "烟", "小", "轩"}
	firstNameLen = len(firstName)
	lastNameLen  = len(lastName)
)
